package org.tuoren.official.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.jsoup.Jsoup;
import org.springframework.stereotype.Service;
import org.tuoren.common.core.exception.ServiceException;
import org.tuoren.common.core.utils.MapstructUtils;
import org.tuoren.common.core.utils.StringUtils;
import org.tuoren.common.mybatis.core.page.PageQuery;
import org.tuoren.common.mybatis.core.page.TableDataInfo;
import org.tuoren.official.domain.Annex;
import org.tuoren.official.domain.TNewsCenter;
import org.tuoren.official.domain.bo.TNewsCenterBo;
import org.tuoren.official.domain.vo.TNewsCenterVo;
import org.tuoren.official.es.domain.TNewsCenterES;
import org.tuoren.official.es.esmapper.ESNewsMapper;
import org.tuoren.official.mapper.TNewsCenterMapper;
import org.tuoren.official.service.ITNewsCenterService;
import org.tuoren.system.service.ISysOssService;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 新闻中心配置Service业务层处理
 *
 * @author Lion Li
 * @since 2024-11-26
 */
@RequiredArgsConstructor
@Service
public class TNewsCenterServiceImpl implements ITNewsCenterService {

    private final TNewsCenterMapper baseMapper;
    private final ESNewsMapper esNewsMapper;
    private final ISysOssService sysOssService;
    /**
     * 查询新闻中心配置
     *
     * @param id 主键
     * @return 新闻中心配置
     */
    @Override
    public TNewsCenterVo queryById(Long id){
        TNewsCenterVo vo = baseMapper.selectVoById(id);
        vo.setAnnexList(JSONUtil.toList(vo.getFileList(), Annex.class));
        return vo;
    }

    /**
     * 分页查询新闻中心配置列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 新闻中心配置分页列表
     */
    @Override
    public TableDataInfo<TNewsCenterVo> queryPageList(TNewsCenterBo bo, PageQuery pageQuery){
        LambdaQueryWrapper<TNewsCenter> lqw = buildQueryWrapper(bo);
        Page<TNewsCenterVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }



    /**
     * 查询符合条件的新闻中心配置列表
     *
     * @param bo 查询条件
     * @return 新闻中心配置列表
     */
    @Override
    public List<TNewsCenterVo> queryList(TNewsCenterBo bo) {
        LambdaQueryWrapper<TNewsCenter> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<TNewsCenter> buildQueryWrapper(TNewsCenterBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<TNewsCenter> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getNewType() != null, TNewsCenter::getNewType, bo.getNewType());
        lqw.like(StringUtils.isNotBlank(bo.getTitle()), TNewsCenter::getTitle, bo.getTitle());
        lqw.eq(StringUtils.isNotBlank(bo.getCoverUrl()), TNewsCenter::getCoverUrl, bo.getCoverUrl());
        lqw.like(StringUtils.isNotBlank(bo.getNewDesc()), TNewsCenter::getNewDesc, bo.getNewDesc());
        lqw.eq(StringUtils.isNotBlank(bo.getContent()), TNewsCenter::getContent, bo.getContent());
        lqw.eq(StringUtils.isNotBlank(bo.getSource()), TNewsCenter::getSource, bo.getSource());
        lqw.eq(StringUtils.isNotBlank(bo.getMediumUrl()), TNewsCenter::getMediumUrl, bo.getMediumUrl());
        lqw.eq(bo.getPublishDate() != null, TNewsCenter::getPublishDate, bo.getPublishDate());
        lqw.eq(StringUtils.isNotBlank(bo.getIsTop()), TNewsCenter::getIsTop, bo.getIsTop());
        return lqw;
    }

    /**
     * 新增新闻中心配置
     *
     * @param bo 新闻中心配置
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(TNewsCenterBo bo) {
        TNewsCenter add = MapstructUtils.convert(bo, TNewsCenter.class);
        add.setFileList(JSONUtil.toJsonStr(bo.getAnnexList()));
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        // 保存成功且为已发布
        if (flag) {
            // 新闻内容数据同步添加到easy-es中
            TNewsCenterES bean = BeanUtil.toBean(add,TNewsCenterES.class);
            Integer year = add.getPublishDate().getYear() + 1900;
            bean.setPublishYear(year);
            Integer month = add.getPublishDate().getMonth() + 1;
            bean.setPublishMonth(month);
            String plainTextContent =StringUtils.isEmpty(bean.getContent()) ? "" :  Jsoup.parse(bean.getContent()).text();
            bean.setContent(plainTextContent);
            esNewsMapper.insert(bean);
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改新闻中心配置
     *
     * @param bo 新闻中心配置
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(TNewsCenterBo bo) {
        TNewsCenter update = MapstructUtils.convert(bo, TNewsCenter.class);
        update.setFileList(JSONUtil.toJsonStr(bo.getAnnexList()));
        validEntityBeforeSave(update);
        Boolean isSave =baseMapper.updateById(update) > 0;
        if(isSave){
            // 查询es中是否存在该条数据
            TNewsCenterES es =esNewsMapper.selectById(bo.getId());
            // 新闻状态为已发布
            if("1".equals(bo.getIsPublish())){
                if (es != null){
                    // 新闻内容数据同步更新到easy-es中
                    TNewsCenterES bean = BeanUtil.toBean(update,TNewsCenterES.class);
                    Integer year = update.getPublishDate().getYear() + 1900;
                    bean.setPublishYear(year);
                    Integer month = update.getPublishDate().getMonth() + 1;
                    bean.setPublishMonth(month);
                    String plainTextContent = StringUtils.isEmpty(bean.getContent()) ? "" :  Jsoup.parse(bean.getContent()).text();
                    bean.setContent(plainTextContent);
                    Integer i =  esNewsMapper.updateById(bean);
                }else{
                    // 新闻内容数据同步添加到easy-es中
                    TNewsCenterES bean = BeanUtil.toBean(update,TNewsCenterES.class);
                    Integer year = update.getPublishDate().getYear() + 1900;
                    bean.setPublishYear(year);
                    Integer month = update.getPublishDate().getMonth() + 1;
                    bean.setPublishMonth(month);
                    String plainTextContent =StringUtils.isEmpty(bean.getContent()) ? "" :  Jsoup.parse(bean.getContent()).text();
                    bean.setContent(plainTextContent);
                    Integer i = esNewsMapper.insert(bean);
                }
            }else{
                // 新闻状态为未发布且es中存在数据
                if(es != null){
                    // 删除es中数据
                    Integer i =   esNewsMapper.deleteById(bo.getId());
                }
            }

        }
        return isSave;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(TNewsCenter entity){
        String newType = entity.getNewType();
        //TODO 做一些数据校验,如唯一约束
        //影像驼人--资源地址必填
        if ("2".equals(newType) && StringUtils.isBlank(entity.getMediumUrl())){
            throw new ServiceException("资源地址不能为空!");
        }
        // 新闻封面除通知公告外，其余必填
        if(!"3".equals(newType) && StringUtils.isBlank(entity.getCoverUrl())){
            throw new ServiceException("新闻封面不能为空!");
        }
        // 新闻内容除影像驼人外必填
        if(!"2".equals(newType) && StringUtils.isBlank(entity.getContent())){
            throw new ServiceException("新闻内容不能为空!");
        }
        // 新闻来源除影像驼人外必填
        if(!"2".equals(newType) && StringUtils.isBlank(entity.getSource())){
            throw new ServiceException("新闻来源不能为空!");
        }
    }

    /**
     * 校验并批量删除新闻中心配置信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        Boolean isDel =baseMapper.deleteByIds(ids) > 0;
        if(isDel){
            // 删除es中相关数据
            esNewsMapper.deleteBatchIds(ids);
        }
        return isDel;
    }

    /**
     * 官网-获取新闻发布年份
     * @return 年份列表
     */
    @Override
    public TableDataInfo<Integer> getPublishYear() {
        List<TNewsCenterVo> list = baseMapper.selectVoList(new LambdaQueryWrapper<TNewsCenter>()
            .eq(TNewsCenter::getIsPublish,"1").orderByDesc(TNewsCenter::getPublishDate));
        List<Integer> years = list.stream().map(vo-> vo.getPublishDate().getYear() + 1900 ).collect(Collectors.toList());
        return TableDataInfo.build(new ArrayList<>(new TreeSet<>(years)));
    }

    /**
     * 官网-获取新闻发布年份-新
     * @return 年份列表
     */
    @Override
    public TableDataInfo<Integer> getPublishYearNew() {
        List<Integer> years = baseMapper.selectPlubilcYearList();
        return TableDataInfo.build(new ArrayList<>(new TreeSet<>(years)));
    }

    /**
     * 官网-获取新闻发布月份
     * @param year 年份（可空）
     * @return 月份列表
     */
    @Override
    public TableDataInfo<Integer> getPublishMonth(String year) {
        SimpleDateFormat sdf = new SimpleDateFormat("M");
        List<TNewsCenterVo> list = baseMapper.selectVoList(new LambdaQueryWrapper<TNewsCenter>()
            .eq(TNewsCenter::getIsPublish,"1")
            .like(StringUtils.isNotBlank(year),TNewsCenter::getPublishDate,year)
        );
        List<Integer> years = list.stream().map(vo-> Integer.parseInt(sdf.format(vo.getPublishDate()))).collect(Collectors.toList());
        Collections.sort(years);
        return TableDataInfo.build(new ArrayList<>(new TreeSet<>(years)));
    }

    /**
     * 官网-获取新闻发布月份
     * @param year 年份（可空）
     * @return 月份列表
     */
    @Override
    public TableDataInfo<Integer> getPublishMonthNew(String year) {
        List<Integer> years = baseMapper.selectPlubilcMonthList(year);
        Collections.sort(years);
        return TableDataInfo.build(years);
    }
    /**
     * 官网-新闻中心配置列表
     * @param newType   新闻类型
     * @param pageQuery 分页参数
     * @return 新闻中心配置分页列表
     */
    @Override
    public TableDataInfo<TNewsCenterVo> getPageList(String newType,PageQuery pageQuery) {
        // 创建一个SimpleDateFormat对象，并指定想要的日期格式
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        LambdaQueryWrapper<TNewsCenter> lqw = new LambdaQueryWrapper<TNewsCenter>().eq(TNewsCenter::getNewType,newType).eq(TNewsCenter::getIsPublish,"1").orderByDesc(TNewsCenter::getPublishDate);
        Page<TNewsCenterVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        List<TNewsCenterVo> list = result.getRecords().stream().map(item->{
            item.setPublishDateFormat(dateFormat.format(item.getPublishDate()));
            return item;
        }).collect(Collectors.toList());
        result.setRecords(list);
        return TableDataInfo.build(result);
    }

    /**
     * 官网-新闻中心配置列表
     * @param newType   新闻类型
     * @param pageQuery 分页参数
     * @return 新闻中心配置分页列表
     */
    @Override
    public TableDataInfo<TNewsCenterVo> getPageListNew(String newType,PageQuery pageQuery) {
        // 创建一个SimpleDateFormat对象，并指定想要的日期格式
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        List<String> newTypeList = CollectionUtil.toList(newType.split(","));
        Page<TNewsCenterVo> result = baseMapper.selectNewCenterList(newTypeList,pageQuery.build());
        List<TNewsCenterVo> list = result.getRecords().stream().map(item->{
            item.setPublishDateFormat(dateFormat.format(item.getPublishDate()));
            return item;
        }).collect(Collectors.toList());
        result.setRecords(list);
        return TableDataInfo.build(result);
    }

    /**
     * 官网-获取新闻详细内容
     * @param id 新闻中心Id
     */
    @Override
    public TNewsCenterVo getNewById(Long id) {
        // 创建一个SimpleDateFormat对象，并指定想要的日期格式
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        TNewsCenterVo vo = baseMapper.selectVoById(id);
        vo.setPublishDateFormat(dateFormat.format(vo.getPublishDate()));
        vo.setAnnexList(JSONUtil.toList(vo.getFileList(), Annex.class));
        return vo;
    }

    /**
     * 官网-新闻列表轮播图
     */
    @Override
    public TableDataInfo<TNewsCenterVo> getTopList(){
        // 创建一个SimpleDateFormat对象，并指定想要的日期格式
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        LambdaQueryWrapper<TNewsCenter> lqw = new LambdaQueryWrapper<TNewsCenter>().eq(TNewsCenter::getIsTop,1).eq(TNewsCenter::getIsPublish,"1").orderByDesc(TNewsCenter::getPublishDate);
        List<TNewsCenterVo> list = baseMapper.selectTopList().stream().map(vo->{
            vo.setPublishDateFormat(dateFormat.format(vo.getPublishDate()));
            return vo;
        }).collect(Collectors.toList());
        return TableDataInfo.build(list);
    }

    /**
     * 官网-新闻、媒体动态详情-随机列表
     * @param newType 新闻类型
     * @param num 显示数量
     */
    @Override
    public TableDataInfo<TNewsCenterVo> getRandomList(String newType,Long num){
        List<TNewsCenterVo> list = new ArrayList<>() ;
        // 创建一个SimpleDateFormat对象，并指定想要的日期格式
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        LambdaQueryWrapper<TNewsCenter> lqw = new LambdaQueryWrapper<TNewsCenter>().eq(TNewsCenter::getNewType,newType).eq(TNewsCenter::getIsPublish,"1");
        // 获取新闻类型数量
        Long count = baseMapper.selectCount(lqw);
        int i=0;
        if(count > 0){
            if(count > num){
                List<TNewsCenterVo> vo = baseMapper.selectVoList(lqw);
                while (true){
                    Random random = new Random();
                    int randomNumber = random.nextInt(count.intValue()) ;
                    if(list.indexOf(vo.get(randomNumber)) == -1){
                        TNewsCenterVo item = vo.get(randomNumber);
                        item.setPublishDateFormat(dateFormat.format(item.getPublishDate()));
                        list.add(item);
                        i++;
                    }
                    if(i == num){
                        break;
                    }
                }
            }else {
                list = baseMapper.selectVoList(lqw);
            }
        }
        return TableDataInfo.build(list);
    }

    /**
     * 官网-新闻、媒体动态详情-随机列表-新
     * @param newType 新闻类型
     * @param num 显示数量
     */
    @Override
    public TableDataInfo<TNewsCenterVo> getRandomListNew(String newType,Long num){
        // 创建一个SimpleDateFormat对象，并指定想要的日期格式
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

        List<TNewsCenterVo>  list= baseMapper.selectRandomList(newType,num);
        list.forEach(item->{
            item.setPublishDateFormat(dateFormat.format(item.getPublishDate()));
        });
        return TableDataInfo.build(list);
    }

    @Override
    public void downLoadAnnex(Long newsId, Long ossId, HttpServletResponse response) throws IOException{
        TNewsCenterVo newsCenterVo = baseMapper.selectVoById(newsId);
        if (newsCenterVo != null){
            List<Annex> annexList = JSONUtil.toList(newsCenterVo.getFileList(), Annex.class);
            for (Annex annex : annexList) {
                if (ossId.equals(annex.getOssId())){
                    try {
                        sysOssService.download(ossId,response);
                        return;
                    } catch (IOException e) {
                        e.printStackTrace();
                        throw new ServiceException("下载失败");
                    }
                }
            }
            throw new ServiceException("下载失败,请检查附件是否正确");
        }else {
        throw new ServiceException("下载失败,该新闻不存在");}
    }
}
